<?php

class NCore_SQLAction implements NCore_IAction
{
	private $dsn = NULL;
	private $password = NULL;
	private $username = NULL;
	private $inputs = array();
	private $name;
	private $returnedValue = NULL;
    private static $dbh = NULL;
	
	function __construct($name = NULL)
	{
		$this->name = $name;
		$this->dsn = N::config('sql_action_dsn');
		$this->username = N::config('sql_action_username');
		$this->password = N::config('sql_action_password');
	}
	public function getName()
	{
		return $this->name;
	}
	public function setReturnedValue($value)
	{
		$this->returnedValue = $value;
	}
	public function getReturnedValue()
	{
		return $this->returnedValue;
	}
	public function withDSN($dsn)
	{
		$this->dsn = $dsn;
		return $this;
	}
	public function withUsername($username)
	{
		$this->username = $username;
		return $this;
	}
	public function withPassword($password)
	{
		$this->password = $password;
		return $this;
	}
	public function withQuery($query)
	{
		$this->query = $query;
		return $this;
	}
	public function withInputs($inputs)
	{
		$this->inputs = $inputs;
		return $this;
	}
	public function getInputs()
	{
		return $this->inputs;	
	}
	public static function getTransactionConnection()
	{
        // eventually augment functionality so you can send in the connection values just like you can for standard SQL Actions
        if(is_null(self::$dbh))
        {
            // add code so you can send in connection info directly
            if(is_null(N::config('sql_action_dsn')) || is_null(N::config('sql_action_username')) || is_null(N::config('sql_action_password')))
            {
                throw new Exception('The nconfig values have a null value for dsn, username, or password and cannot connect to the database.  Values can be set explicitly on this particular SQLAction, or defaults can be set in the config file.');
            }

            self::$dbh = new PDO(N::config('sql_action_dsn'), N::config('sql_action_username'), N::config('sql_action_password'));
            self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }

        self::$dbh->beginTransaction();

		return self::$dbh;
	}
	protected function getConnection()
	{
		if(is_null($this->dsn) || is_null($this->username) || is_null($this->password))
		{
			throw new Exception('The SQLAction \''.$this->name.'\' has a null value for dsn, username, or password and cannot connect to the database.  Values can be set explicitly on this particular SQLAction, or defaults can be set in the config file.');
		}
		
		$dbh = new PDO($this->dsn, $this->username, $this->password);
		$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		
		return $dbh;
	}
	protected function getObjValues($values)
	{
		$newValues = array();
	
		foreach($values as $key=>$value)
		{
			if($value instanceof NCore_IValue)
			{
				$newValues[$key] = $value->getValue();
			}
			else
			{
				$newValues[$key] = $value;
			}
		}
		
		return $newValues;
	}
	protected function runSQL($dbh)
	{
		$stmt = $dbh->prepare($this->query);
		
		if(!$stmt->execute($this->inputs))
		{
			throw new Exception('The query in the \''.$this->name.'\' SQLAction could not be completed.');
		}
		
		if(strtolower(substr(trim($this->query), 0, 6)) == 'insert')
		{
			try{
				$this->setReturnedValue($dbh->lastInsertId());
			}
			catch(Exception $e)
			{
				// do nothing
			}
		}
	}
	public function run()
	{
		$this->inputs = $this->getObjValues($this->inputs);
        if(is_null(self::$dbh))
        {
            $dbh = $this->getConnection();
            $this->runSQL($dbh);
            $dbh = NULL;
        }
        // otherwise, running as transaction
        else
        {
            $this->runSQL(self::$dbh);
        }
		return $this->getReturnedValue();
	}
	public static function beginSQLTransaction()
    {
        return self::getTransactionConnection();
    }
    public static function commitSQLTransaction()
    {
        return self::$dbh->commit();
    }
    public static function rollbackSQLTransaction()
    {
        self::$dbh->rollBack();
        return self::$dbh = NULL;
    }
}

?>